package utils

import (
	"bytes"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"github.com/golang/protobuf/jsonpb"
	"github.com/golang/protobuf/proto"
	"manager/lib/trace_log"
	"math"
	"math/rand"
	"net/http"
	"reflect"
	"regexp"
	"runtime/debug"
	"strconv"
	"time"
)

import (
	"github.com/gin-gonic/gin"
)

func Throw(err error) {
	if err != nil {
		panic(err)
	}
}

func ExceptionCatch() {
	if err := recover(); err != nil {
		trace_log.ErrorLogger.Info("Exception err:", err, " \n stack:", string(debug.Stack()))
	}
}

const fixedStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" // 固定字符串
type RespModel struct {
	Code    int         `json:"code"`
	Message string      `json:"msg"`
	Data    interface{} `json:"data"`
}

// RespOK 请求成功返回
func ResponseOk(c *gin.Context, data interface{}) {
	d := RespModel{
		Code:    0,
		Message: "ok",
		Data:    data,
	}
	c.Header("Cache-Control", "max-age=60")
	c.JSON(http.StatusOK, d)
}

func ToJsonString(data interface{}) string {
	return string(toJson(data))
}

func ToJsonBytes(data interface{}) []byte {
	return toJson(data)
}

func toJson(data interface{}) []byte {
	if data == nil {
		return nil
	}
	marshal, _ := json.Marshal(data)
	return marshal
}

// ToMap 结构体转为Map[string]interface{}
func ToMap(in interface{}) (map[string]interface{}, error) {
	out := make(map[string]interface{})

	v := reflect.ValueOf(in)
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}

	if v.Kind() != reflect.Struct { // 非结构体返回错误提示
		return nil, fmt.Errorf("ToMap only accepts struct or struct pointer; got %T", v)
	}

	t := v.Type()
	// 遍历结构体字段
	// 指定tagName值为map中key;字段值为map中value
	for i := 0; i < v.NumField(); i++ {
		fi := t.Field(i)
		if tagValue := fi.Tag.Get("json"); tagValue != "" {
			out[tagValue] = v.Field(i).Interface()
		}
	}
	return out, nil
}

// PageUtil 分页工具
func PageUtil(size, index int) (int, int) {
	if index == 0 {
		index = 1
	}
	if size > 500 {
		size = 500
	}
	return size, index
}

// EncryptionSha256 密码加密
func EncryptionSha256(password, salt string) string {
	str := fmt.Sprintf("%s%s", password, salt)
	return base64.RawURLEncoding.EncodeToString(sha256.New().Sum([]byte(str)))
}

func PageCount(total, pageSize int64) int64 {
	return int64(math.Ceil(float64(total) / float64(pageSize)))
}
func RandString(count int) string {
	rand.Seed(time.Now().UnixNano()) // 使用当前时间作为随机数种子
	var result string                // 存储结果的字符串
	for i := 0; i < count; i++ {
		result += string(fixedStr[rand.Intn(len(fixedStr))]) // 从固定字符串中随机选择一个字符
	}
	return result
}

func GenerateRandomIntCode(digit int) int {
	if digit < 1 {
		digit = 4
	}

	rand.Seed(time.Now().UnixNano())

	// 计算最小值和最大值
	min := int64(1)
	for i := 1; i < digit; i++ {
		min *= 10
	}
	max := min*10 - 1
	return int(rand.Int63n(max-min+1) + min)
}

func StrToInt64(value string) int64 {
	dst, err := strconv.ParseInt(value, 10, 64)
	if err != nil {
		return 0
	}
	return int64(dst)
}

func TransProtoToJson(data proto.Message) (mapData map[string]interface{}, err error) {
	var marshal jsonpb.Marshaler
	marshal = jsonpb.Marshaler{
		EmitDefaults: true,
		OrigName:     true,
		EnumsAsInts:  true,
	}
	_buffer := new(bytes.Buffer)
	if err = marshal.Marshal(_buffer, data); err != nil {
		return
	}

	mapData = map[string]interface{}{}
	err = json.Unmarshal(_buffer.Bytes(), &mapData)
	return
}

// SqlLike sql模糊查询
func SqlLike(col *string) string {
	return fmt.Sprintf("%v", "%"+*col+"%")
}

// VerifyEmailFormat email verify
func VerifyEmailFormat(email string) bool {
	//pattern := `\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*` //匹配电子邮箱
	pattern := `^[0-9a-z][_.0-9a-z-]{0,31}@([0-9a-z][0-9a-z-]{0,30}[0-9a-z]\.){1,4}[a-z]{2,4}$`

	reg := regexp.MustCompile(pattern)
	return reg.MatchString(email)
}

// VerifyMobileFormat mobile verify
func VerifyMobileFormat(mobileNum string) bool {
	regular := "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$"

	reg := regexp.MustCompile(regular)
	return reg.MatchString(mobileNum)
}
